#include <am.h>
#include <nemu.h>

#define AUDIO_FREQ_ADDR      (AUDIO_ADDR + 0x00)
#define AUDIO_CHANNELS_ADDR  (AUDIO_ADDR + 0x04)
#define AUDIO_SAMPLES_ADDR   (AUDIO_ADDR + 0x08)
#define AUDIO_SBUF_SIZE_ADDR (AUDIO_ADDR + 0x0c)
#define AUDIO_INIT_ADDR      (AUDIO_ADDR + 0x10)
#define AUDIO_COUNT_ADDR     (AUDIO_ADDR + 0x14)
#define AUDIO_LENGTH_ADDR    (AUDIO_ADDR + 0x18)

void __am_audio_init() {
  inl(AUDIO_INIT_ADDR);
}

void __am_audio_config(AM_AUDIO_CONFIG_T *cfg) {
  cfg->present = true;
  cfg->bufsize = inl(AUDIO_SBUF_SIZE_ADDR);
}

void __am_audio_ctrl(AM_AUDIO_CTRL_T *ctrl) {;
  outl(AUDIO_FREQ_ADDR,ctrl->freq);
  outl(AUDIO_CHANNELS_ADDR,ctrl->channels);
  outl(AUDIO_SAMPLES_ADDR,ctrl->samples);
  outl(AUDIO_COUNT_ADDR,0);
}

void __am_audio_status(AM_AUDIO_STATUS_T *stat) {
  stat->count = inl(AUDIO_COUNT_ADDR);
}

void __am_audio_play(AM_AUDIO_PLAY_T *ctl) {
  int len = ctl->buf.end - ctl->buf.start;
  uint32_t *buf32=ctl->buf.start;
  int len4=len&0x3;
  int len1=len-len4;
  int nwrite = 0;
  while (nwrite < len4) {
    outl(AUDIO_SBUF_ADDR + nwrite,buf32[nwrite]);
    nwrite += sizeof(uint32_t);
  }
  uint8_t* buf8=(uint8_t*)(buf32+nwrite);
  nwrite=0;
  while (nwrite < len1) {
    outl(AUDIO_SBUF_ADDR + nwrite,buf8[nwrite]);
    nwrite += sizeof(uint8_t);
  }
  outl(AUDIO_LENGTH_ADDR,len);
}
